﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using UtilZ.Dotnet.Ex.Base;
using UtilZ.Dotnet.Ex.Log;

namespace WinFormApp
{
    public partial class UCSplitDataControl : UserControl
    {
        public UCSplitDataControl()
        {
            InitializeComponent();
        }

        private ThreadEx _splitThread = null;
        private void UCSplitDataControl_Load(object sender, EventArgs e)
        {
            this._splitThread = new ThreadEx(this.SplitThreadMethod, "数据拆分线程", true);
            this._splitThread.Completed += _splitThread_Completed;
        }

        private void _splitThread_Completed(object sender, ThreadExCompletedArgs e)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(() =>
                {
                    btnSplit.Enabled = true;
                });
            }
            else
            {
                btnSplit.Enabled = true;
            }
        }

        private void btnChioceSrcFile_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Multiselect = false;
            if (ofd.ShowDialog() == DialogResult.OK)
            {
                txtSrcFilePath.Text = ofd.FileName;
            }
        }

        private void btnChioceDstPath_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog fbd = new FolderBrowserDialog();
            if (fbd.ShowDialog() == DialogResult.OK)
            {
                txtDstPath.Text = fbd.SelectedPath;
            }
        }

        private bool _spliting = false;
        private void btnSplit_Click(object sender, EventArgs e)
        {
            try
            {
                if (this._spliting)
                {
                    this._spliting = false;
                    this._splitThread.Stop();
                }
                else
                {

                    string srcFilePath = txtSrcFilePath.Text.Trim();
                    if (string.IsNullOrWhiteSpace(srcFilePath))
                    {
                        Loger.Warn("用于拆分的原数据文件路径不能为空");
                        return;
                    }

                    if (!File.Exists(srcFilePath))
                    {
                        Loger.Warn($"用于拆分的原数据文件\"{srcFilePath}\"不存在");
                        return;
                    }

                    string dstPath = txtDstPath.Text.Trim();
                    if (string.IsNullOrWhiteSpace(dstPath))
                    {
                        Loger.Warn("存放拆分输出数据文件路径不能为空");
                        return;
                    }

                    if (!Directory.Exists(dstPath))
                    {
                        Directory.CreateDirectory(dstPath);
                    }

                    var options = new SplitOptions();
                    options.SrcFilePath = srcFilePath;
                    options.DstPath = dstPath;
                    options.Pre = txtSplitPre.Text.Trim();
                    options.StartPosition = (long)numStartPostion.Value;
                    options.BlockSize = (long)numBlockSize.Value;
                    options.BlockCount = (int)numBlockCount.Value;

                    this._spliting = true;
                    btnSplit.Enabled = false;
                    this._splitThread.Start(options);
                }
            }
            catch (Exception ex)
            {
                Loger.Error(ex);
            }
        }

        private void SplitThreadMethod(ThreadPara threadPara)
        {
            try
            {
                Loger.Info("拆分数据文件开始.");
                var options = (SplitOptions)threadPara.Para;

                byte[] buffer = new byte[4096];
                using FileStream srcFileStream = new FileStream(options.SrcFilePath, FileMode.Open, FileAccess.Read, FileShare.Read);
                if (options.StartPosition >= srcFileStream.Length)
                {
                    Loger.Warn($"拆分数据文件起始位置超出了原始文件长度.");
                    return;
                }

                srcFileStream.Position = options.StartPosition;
                string splitSubFilePath;
                int readLen, readedLen;
                long modReadLength;
                int blockCount = 0;

                while (!threadPara.Token.IsCancellationRequested)
                {
                    if (string.IsNullOrEmpty(options.Pre))
                    {
                        splitSubFilePath = PathEx.Combine(PathType.Local, options.DstPath, $"{srcFileStream.Position}_{srcFileStream.Position + options.BlockSize}.dat");
                    }
                    else
                    {
                        splitSubFilePath = PathEx.Combine(PathType.Local, options.DstPath, $"{options.Pre}_{srcFileStream.Position}_{srcFileStream.Position + options.BlockSize}.dat");
                    }

                    using var splitSubFileStream = new FileStream(splitSubFilePath, FileMode.Create, FileAccess.Write);
                    readLen = buffer.Length;
                    while (!threadPara.Token.IsCancellationRequested)
                    {
                        modReadLength = options.BlockSize - splitSubFileStream.Position;
                        if (modReadLength < readLen)
                        {
                            readLen = (int)modReadLength;
                        }
                        readedLen = srcFileStream.Read(buffer, 0, readLen);
                        splitSubFileStream.Write(buffer, 0, readedLen);

                        if (readedLen < readLen || splitSubFileStream.Position >= options.BlockSize)
                        {
                            break;
                        }
                    }

                    blockCount++;
                    if (blockCount >= options.BlockCount)
                    {
                        break;
                    }
                }

                Loger.Info("拆分数据文件结束.");
            }
            catch (Exception ex)
            {
                Loger.Error(ex, "拆分数据文件异常.");
            }
            this._spliting = false;
        }


        private class SplitOptions
        {
            public string SrcFilePath { get; set; }
            public string DstPath { get; set; }
            public string Pre { get; set; }
            public long StartPosition { get; set; }
            public long BlockSize { get; set; }
            public int BlockCount { get; set; }

            public SplitOptions()
            {

            }
        }
    }
}
